package com.yuantu.judiciary.model.word;

import lombok.Data;
import org.apache.poi.xwpf.usermodel.*;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.springframework.util.CollectionUtils;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Collectors;

/**
 * @author kgwei
 * 表格
 */
@Data
public class WordTable implements WordElement {

    private int rows;

    private int cols;

    private List<WordTableRow> tableRows;

    private List<WordTableMerge> merges;

    private boolean avgColWidth;

    /**
     * 有标题的表格
     * @param titles .
     * @param data .
     * @return .
     */
    public static WordTable defaultTableWithTitle(List<String> titles, List<List<String>> data) {
        if (CollectionUtils.isEmpty(titles)) {
            return defaultTableWithData(data);
        }
        WordTable wordTable = defaultTableWithData(data);
        wordTable.setRows(wordTable.getRows() + 1);
        if (wordTable.getCols() < titles.size()) {
            wordTable.setCols(titles.size());
        }
        WordTableRow titleRow = WordTableRow.defaultRow();
        List<WordTableCell> titleCells = new ArrayList<>();
        for (String title: titles) {
            titleCells.add(WordTableCell.defaultTitleCell(title));
        }
        titleRow.setCells(titleCells);
        wordTable.getTableRows().add(0, titleRow);
        return wordTable;
    }

    public static WordTable defaultTableWithTitle(String[] titles, String[][] data) {
        if (titles == null || titles.length == 0) {
            return defaultTableWithData(data);
        }
        return defaultTableWithTitle(Arrays.asList(titles), Arrays.stream(data).map(Arrays::asList).collect(Collectors.toList()));
    }

    public static WordTable defaultTableWithData(List<List<String>> data) {
        String[][] array = new String[data.size()][];
        for (int i = 0; i < data.size(); i++) {
            List<String> row = data.get(i);
            array[i] = row.toArray(new String[0]);
        }
        return defaultTableWithData(array);
    }

    public static WordTable defaultTableWithData(String[][] data) {
        WordTable wordTable = new WordTable();
        int rows = 0;
        int cols = 0;
        List<WordTableRow> tableRows = new ArrayList<>();
        for (String[] row: data) {
            rows++;
            cols = Math.max(row.length, cols);
            WordTableRow wordTableRow = new WordTableRow();
            wordTableRow.setHeight(WordDefaultValue.TABLE_ROW_HEIGHT);
            List<WordTableCell> wordTableCells = new ArrayList<>();
            for (String cell: row) {
                WordTableCell wordTableCell = new WordTableCell();
                wordTableCell.setText(cell);
                wordTableCell.setFontSize(WordDefaultValue.TABLE_DATA_FONT_SIZE);
                wordTableCell.setAlignment(ParagraphAlignment.CENTER);
                wordTableCell.setVAlign(STVerticalJc.CENTER);
                wordTableCells.add(wordTableCell);
            }
            wordTableRow.setCells(wordTableCells);
            tableRows.add(wordTableRow);
        }
        wordTable.setTableRows(tableRows);
        wordTable.setCols(cols);
        wordTable.setRows(rows);
        return wordTable;
    }

    @Override
    public WordElementType getElementType() {
        return WordElementType.TABLE;
    }

    @Override
    public void addElement(XWPFDocument document) {
        XWPFTable table = document.createTable(rows, cols);
        CTTblPr tblPr = table.getCTTbl().getTblPr();
        CTTblWidth tblWidth = tblPr.addNewTblW();
        tblWidth.setW(BigInteger.valueOf(5000));
        tblWidth.setType(STTblWidth.PCT);
        List<XWPFTableRow> rows = table.getRows();
        int cellWidth = 5000 / cols;
        int rowCt = 0;
        for (WordTableRow wordTableRow: tableRows) {
            XWPFTableRow row = rows.get(rowCt);
            wordTableRow.rowBuild(row);
            if (!CollectionUtils.isEmpty(wordTableRow.getCells())) {
                int colCt = 0;
                List<XWPFTableCell> cells = row.getTableCells();
                for (WordTableCell wordTableCell: wordTableRow.getCells()) {
                    XWPFTableCell cell = cells.get(colCt);
                    if (avgColWidth) {
                        wordTableCell.setWidthPct(cellWidth);
                        wordTableCell.setWithType(STTblWidth.DXA);
                    }
                    wordTableCell.cellBuild(cell);
                    colCt++;
                }
            }
            rowCt++;
        }
        if (!CollectionUtils.isEmpty(merges)) {
            for (WordTableMerge merge: merges) {
                if (merge.getMergeType() == WordTableMergeType.HORIZON) {
                    mergeCellsHorizontally(table, merge.getPos(), merge.getFrom(), merge.getTo());
                } else {
                    mergeCellsVertically(table, merge.getPos(), merge.getFrom(), merge.getTo());
                }
            }
        }
    }

    /**
     * 水平合并单元格
     * @param table .
     * @param row .
     * @param fromCell .
     * @param toCell .
     */
    private void mergeCellsHorizontally(XWPFTable table, int row, int fromCell, int toCell) {
        XWPFTableRow tableRow = table.getRow(row);
        for (int cellIndex = fromCell; cellIndex <= toCell; cellIndex++) {
            XWPFTableCell cell = tableRow.getCell(cellIndex);
            if (cellIndex == fromCell) {
                // 设置合并起始单元格
                cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.RESTART);
            } else {
                // 设置合并中的单元格
                cell.getCTTc().addNewTcPr().addNewHMerge().setVal(STMerge.CONTINUE);
            }
        }
    }

    /**
     * 垂直合并单元格
     * @param table .
     * @param col .
     * @param fromRow .
     * @param toRow .
     */
    private void mergeCellsVertically(XWPFTable table, int col, int fromRow, int toRow) {
        for (int rowIndex = fromRow; rowIndex <= toRow; rowIndex++) {
            XWPFTableCell cell = table.getRow(rowIndex).getCell(col);
            if (rowIndex == fromRow) {
                // 设置合并起始单元格
                cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.RESTART);
            } else {
                // 设置合并中的单元格
                cell.getCTTc().addNewTcPr().addNewVMerge().setVal(STMerge.CONTINUE);
            }
        }
    }
}
